class WordDictionary {
    private static class Trie {
        Trie[] child;
        boolean isEnd;

        Trie() {
            child = new Trie[26];
            isEnd = false;
        }

        void insert(String word) {
            Trie node = this;
            for (int i = 0; i < word.length(); i++) {
                int index = word.charAt(i) - 'a';
                if (node.child[index] == null) {
                    node.child[index] = new Trie();
                }
                node = node.child[index];
            }
            node.isEnd = true;
        }

        boolean search(String word) {
            return dfs(word, 0, this);
        }

        boolean dfs(String word, int i, Trie node) {
            if (i == word.length()) {
                return node.isEnd;
            }
            char ch = word.charAt(i);
            if (ch != '.') {
                int index = ch - 'a';
                return node.child[index] != null && dfs(word, i + 1, node.child[index]);
            } else {
                for (int k = 0; k < 26; k++) {
                    if (node.child[k] != null && dfs(word, i + 1, node.child[k])) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    Trie trie;

    public WordDictionary() {
        trie = new Trie();
    }

    public void addWord(String word) {
        trie.insert(word);
    }

    public boolean search(String word) {
        return trie.search(word);
    }
}